package com.zmn.oms.zmn.normal.business.impl.work.masterwork;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.base.price.common.dro.item.ItemPartsDRO;
import com.zmn.base.price.dubbo.interfaces.item.ItemPartsRemoteService;
import com.zmn.common.constant.FicoConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.manager.redis.lock.DistributedLock;
import com.zmn.manager.redis.lock.DistributedLockUtils;
import com.zmn.oms.business.interfaces.completecode.CompleteCodeBService;
import com.zmn.oms.business.interfaces.conf.channel.ConfOrderChannelBService;
import com.zmn.oms.business.interfaces.discount.OrderDiscountBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountCalcBService;
import com.zmn.oms.business.interfaces.part.OrderPartBService;
import com.zmn.oms.business.interfaces.warranty.OrderWarrantyBService;
import com.zmn.oms.business.interfaces.work.OrderWorkAmountBService;
import com.zmn.oms.business.interfaces.work.OrderWorkPositionBService;
import com.zmn.oms.common.annotation.OrderWorkCasOperate;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dro.conf.channel.ConfOrderChannelDRO;
import com.zmn.oms.common.enums.WorkPartUseTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.MathUtil;
import com.zmn.oms.common.utils.PremissUtil;
import com.zmn.oms.common.vo.KVDict;
import com.zmn.oms.model.bo.orderamount.OrderAmountCalcBO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.bo.work.ChangeOriginalAmountDiscountBO;
import com.zmn.oms.model.dto.acceptance.OrderWorkAcceptanceDTO;
import com.zmn.oms.model.dto.discount.MemberDiscountDTO;
import com.zmn.oms.model.dto.fcorderpart.FcOrderPartCheckDTO;
import com.zmn.oms.model.dto.messageV1.AppMessageDTO;
import com.zmn.oms.model.dto.part.SingleMasterOrderPartDTO;
import com.zmn.oms.model.dto.work.masterwork.CompleteDTO;
import com.zmn.oms.model.dto.work.masterwork.ContactUserDTO;
import com.zmn.oms.model.dto.work.masterwork.ServiceCompleteDIO;
import com.zmn.oms.model.dto.work.modify.amount.ZsUpdateChannelPrepayAmountDTO;
import com.zmn.oms.model.dto.work.modify.amount.ZsUpdatePriceDTO;
import com.zmn.oms.model.dto.work.workamount.WorkUpdateAmountDTO;
import com.zmn.oms.model.entity.channelprepay.OrderChannelPrepay;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.member.OrderMember;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.part.OrderPart;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.visit.OrderVisit;
import com.zmn.oms.model.entity.visit.OrderVisitQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.pay.OrderPayVO;
import com.zmn.oms.model.vo.work.OperatePermissionVO;
import com.zmn.oms.model.vo.work.modify.amount.ZsUpdateChannelPrepayAmountVO;
import com.zmn.oms.model.vo.work.modify.amount.ZsUpdatePriceDiscountVO;
import com.zmn.oms.model.vo.work.modify.amount.ZsUpdatePriceVO;
import com.zmn.oms.services.interfaces.channelprepay.OrderChannelPrepayService;
import com.zmn.oms.services.interfaces.conf.channel.ConfOrderChannelService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.fcorderpart.OrderFactoryPartService;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.member.OrderMemberService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.orderattachment.OrderAttachmentService;
import com.zmn.oms.services.interfaces.part.OrderPartService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.product.OrderProductExtendService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.serviceitem.OrderServiceItemService;
import com.zmn.oms.services.interfaces.track.OrderTrackService;
import com.zmn.oms.services.interfaces.visit.OrderVisitService;
import com.zmn.oms.services.interfaces.warranty.OrderWarrantyProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkAmountService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.jddj.service.JddjService;
import com.zmn.oms.third.tmall.service.TmallService;
import com.zmn.oms.third.zhimi.service.ZhimiOrderExtendService;
import com.zmn.oms.zmn.business.interfaces.acceptance.OrderWorkAcceptanceBService;
import com.zmn.oms.zmn.business.interfaces.part.ZsOrderFactoryPartBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.ZsOrderPayBService;
import com.zmn.oms.zmn.normal.business.interfaces.discount.ZsNormalOrderDiscountBService;
import com.zmn.oms.zmn.normal.business.interfaces.part.ZsNormalOrderPartBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.masterwork.ZsNormalMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.scm2.common.model.dro.scm.purchase.apply.ScmPurchaseApplyDRO;
import com.zmn.scm2.common.model.query.scm.purchase.apply.ScmPurchaseApplyQuery;
import com.zmn.scm2.dubbo.interfaces.scm.engineer.purchase.EngineerPurchaseListRemoteService;
import com.zmn.scm2.dubbo.interfaces.scm.maintenance.order.use.MaintenanceOrderUseListRemoteService;
import com.zmn.track.common.constant.TrackConfigConsts;
import com.zmn.track.common.constant.TrackConsts;
import com.zmn.track.common.dio.TrackWorkQueryDIO;
import com.zmn.track.dubbo.dto.TrackWorkDRO;
import com.zmn.track.dubbo.interfaces.trackwork.TrackWorkListRemoteService;
import com.zmn.vas.dubbo.interfaces.order.VasOrderListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 类描述：工程师工单业务实现
 *
 * @author heciqi
 * @date 2018/11/02 21:02
 */
@Slf4j
@Service
public class ZsNormalMasterWorkBServiceImpl implements ZsNormalMasterWorkBService {

    @Autowired
    protected OrderMasterService orderMasterService;
    @Autowired
    protected OrderWorkService orderWorkService;
    @Autowired
    protected OrderDetailService orderDetailService;
    @Autowired
    protected OrderWorkAmountService orderWorkAmountService;
    @Autowired
    protected ZsNormalOrderDiscountBService zsNormalOrderDiscountService;
    @Autowired
    protected OrderDiscountBService orderDiscountBService;
    @Autowired
    protected OrderDiscountService orderDiscountService;
    @Autowired
    protected OrderProductService orderProductService;
    @Autowired
    protected OrderWorkAmountBService orderWorkAmountBService;
    @Autowired
    protected ZsMasterWorkBService zsMasterWorkBService;
    @Autowired
    protected ZhimiOrderExtendService zhimiOrderExtendService;
    @Autowired
    protected OrderExtendService orderExtendService;
    @Autowired
    protected OrderServiceItemService orderServiceItemService;
    @Autowired
    protected OrderFactoryPartService orderFactoryPartService;
    @Autowired
    protected OrderAttachmentService orderAttachmentService;
    @Autowired
    protected ZsOrderWorkOperatePermissionBService orderWorkOperatePermissionBService;
    @Autowired
    protected ZsOrderFactoryPartBService zsOrderFactoryPartBService;
    @Autowired
    protected OrderAmountCalcBService orderAmountCalcBService;
    @Autowired
    protected OrderProductExtendService orderProductExtendService;
    @Autowired
    protected OrderWorkPositionBService orderWorkPositionBService;
    @Autowired
    protected OrderMemberService orderMemberService;
    @Autowired
    protected OrderWarrantyBService orderWarrantyBService;
    @Autowired
    protected OrderWarrantyProductService orderWarrantyProductService;
    @Autowired
    protected OrderTrackService orderTrackService;
    @Autowired
    protected ZsOrderPayBService zsOrderPayBService;
    @Autowired
    protected OrderPartService orderPartService;
    @Autowired
    private JddjService jddjService;
    @Autowired
    private TmallService tmallService;
    @Autowired
    private ZsOrderWorkOperatePermissionBService zsOrderWorkOperatePermissionBService;
    @Autowired
    private CompleteCodeBService completeCodeBService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private OrderVisitService orderVisitService;
    @Autowired
    private MessageSendBaseService messageSendBaseService;
    @Autowired
    private OrderWorkAcceptanceBService orderWorkAcceptanceBService;
    @Autowired
    private OrderPartBService orderPartBService;
    @Autowired
    private ZsNormalOrderPartBService zsNormalOrderPartBService;
    @Autowired
    private OrderChannelPrepayService orderChannelPrepayService;
    @Autowired
    private ConfOrderChannelService confOrderChannelService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerListRemoteService engineerListRemoteService;
    @Resource
    private ConfOrderChannelBService confOrderChannelBService;
    @Reference(version = com.zmn.vas.dubbo.consts.VasDubboConsts.INTERFACE_VERSION, check = false)
    private VasOrderListRemoteService vasOrderListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemPartsRemoteService itemPartsRemoteService;
    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private MaintenanceOrderUseListRemoteService maintenanceOrderUseListRemoteService;
    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerPurchaseListRemoteService engineerPurchaseListRemoteService;
    @Reference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private TrackWorkListRemoteService trackWorkListRemoteService;

    @Override
    public ZsUpdatePriceVO findUpdatePriceVO(Long orderId, Long workId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        ZsUpdatePriceVO updatePriceVO = BeanMapper.map(orderWork, ZsUpdatePriceVO.class);
        updatePriceVO.setStandardPrice(GlobalConsts.YES);

        // 啄木鸟预收 + 渠道预收
        Integer prepayAmount = Optional.ofNullable(orderWork.getPrepayAmount()).orElse(0);
        Integer channelPrepayAmount = Optional.ofNullable(orderWork.getChannelPrepayAmount()).orElse(0);
        updatePriceVO.setPrepayAmount(prepayAmount + channelPrepayAmount);

        // 转换优惠VO
        List<OrderDiscount> discountList = orderDiscountService.listByOrderId(orderId);
        List<ZsUpdatePriceDiscountVO> discountVOList = BeanMapper.mapList(discountList, ZsUpdatePriceDiscountVO.class);
        discountVOList.forEach(discount -> {
            discount.setCategName(FicoConsts.getDiscountCategName(discount.getCateg()));
            discount.setTypeName(OrderConsts.getDiscountTypeName(discount.getType()));
        });
        updatePriceVO.setDiscountVOList(discountVOList);

        // 如果是会员单检查会员权益
        Integer member = orderWork.getMember();
        if (Objects.equals(GlobalConsts.YES, member)) {
            Optional<OrderDiscount> memDiscount = discountList.stream().filter(discount -> Objects.equals(discount.getCateg(), FicoConsts.ORDER_IN_DISCOUNT_CATEG_MEMBER)).findAny();
            boolean isHasEqutity = memDiscount.isPresent();
            if (isHasEqutity) {
                updatePriceVO.setEqutityId(memDiscount.get().getSourceId());
            }
        }

        // 是否是清洗
        boolean clean = Objects.equals(orderWork.getServCategId(), GlobalConsts.SERV_CATEG_CLEAN);
        updatePriceVO.setClean(clean ? GlobalConsts.YES : GlobalConsts.NO);

        //支付明细
        List<OrderPay> orderPayList = orderPayService.listOrderPayByOrderId(orderId);
        if (CollectionUtil.isNotNullOrEmpty(orderPayList)) {
            AtomicReference<Integer> amount = new AtomicReference<>(0);
            List<OrderPayVO> resultList = Lists.newArrayListWithCapacity(orderPayList.size());
            // 定金、进度款
            orderPayList.forEach(pay -> {
                // 过滤重复支付
                if (Objects.equals(pay.getDuplicate(), GlobalConsts.YES)) {
                    return;
                }
                OrderPayVO orderPayVO = BeanMapper.map(pay, OrderPayVO.class);
                orderPayVO.setAmountTypeName(OrderPayConsts.getAmountTypeName(orderPayVO.getAmountType()));
                orderPayVO.setPayStatusName(PayConsts.getPayStatusName(orderPayVO.getPayStatus()));
                orderPayVO.setPayTypeName(PayConsts.getPayTypeName(orderPayVO.getPayType()));
                resultList.add(orderPayVO);
                if (Objects.equals(orderPayVO.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                    updatePriceVO.setOldAmount(orderPayVO.getAmount());
                    amount.updateAndGet(v -> v + orderPayVO.getAmount());
                }
            });
            updatePriceVO.setMasterAmount(Optional.ofNullable(updatePriceVO.getMasterAmount()).orElse(0) - amount.get());
            updatePriceVO.setOrderPayList(resultList);
        }

        return updatePriceVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_PLAT_UPDATE_PRICE)
    public void saveUpdatePrice(ZsUpdatePriceDTO updatePriceDTO) throws OmsBaseException {

        OperatePermissionVO operatePermission = orderWorkOperatePermissionBService.getOperatePermission(updatePriceDTO.getOrderId(), updatePriceDTO.getWorkId(), OrderConsts.ORDER_OP_TYPE_UPDATE_PRICE);
        if (!operatePermission.getCanOperate()) {
            throw new OmsBaseException(operatePermission.getMsg());
        }

        //OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(updatePriceDTO.getOrderId(), updatePriceDTO.getWorkId());

        if (!Objects.equals(updatePriceDTO.getOldAmount(), updatePriceDTO.getAmount())) {
            OrderWork orderWork = orderWorkService.findOrderWorkByKey(updatePriceDTO.getOrderId(), updatePriceDTO.getWorkId());

            OrderPay orderPay = new OrderPay();
            orderPay.setOrderId(updatePriceDTO.getOrderId());
            orderPay.setOrderPayId(updatePriceDTO.getOrderPayId());
            orderPay.setAmount(updatePriceDTO.getAmount());
            orderPay.setUpdater(updatePriceDTO.getOperator());
            // 如果改为0则删除支付明细
            if (Objects.equals(updatePriceDTO.getAmount(), com.zmn.consts.GlobalConsts.NONE)) {
                orderPay.setDeleted(com.zmn.consts.GlobalConsts.YES);
            }
            orderPayService.updateByPrimaryKeySelective(orderPay);

            OrderVisit orderVisit = new OrderVisit();
            orderVisit.setOrderId(updatePriceDTO.getOrderId());
            // 如果改为0则删除支付明细
            if (Objects.equals(updatePriceDTO.getAmount(), com.zmn.consts.GlobalConsts.NONE)) {
                orderVisit.setOrderPayId(0L);
                orderVisit.setPayStatus(com.zmn.consts.GlobalConsts.NONE);
            } else {
                orderVisit.setOrderPayId(updatePriceDTO.getOrderPayId());
            }
            orderVisit.setAmount(updatePriceDTO.getAmount());
            orderVisit.setUpdater(updatePriceDTO.getOperator());

            OrderVisitQuery query = new OrderVisitQuery();
            query.setOrderId(updatePriceDTO.getOrderId());
            query.setOrderPayId(updatePriceDTO.getOrderPayId());
            OrderVisit dbOrderVisit = orderVisitService.findOrderVisitByQuery(query);
            // 如果存在验收id，则取消本次验收
            if (NumberUtil.isNotNullOrZero(dbOrderVisit.getAcceptanceId())) {
                OrderWorkAcceptanceDTO dto = BeanMapper.map(updatePriceDTO, OrderWorkAcceptanceDTO.class);
                dto.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL);
                orderWorkAcceptanceBService.modifyOrderWorkAcceptance(dto);

                orderVisit.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL);
            }

            orderVisitService.updatePayStatusByKey(orderVisit);

            // 改价格发送app push消息
            Map<String, Object> params = Maps.newHashMap();
            params.put("order_id", String.valueOf(updatePriceDTO.getOrderId()));
            params.put("work_id", String.valueOf(updatePriceDTO.getWorkId()));

            AppMessageDTO appMessageDTO = new AppMessageDTO();
            appMessageDTO.setOrderId(orderWork.getOrderId());
            appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
            appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
            appMessageDTO.setPlat(orderWork.getPlatWork());
            appMessageDTO.setMasterId(orderWork.getMasterId());
            appMessageDTO.setRuleId(MessageConsts.APP_PUSH_MSG_RULE_ID_ENGINEER_AGAIN_CONFIRM);
            appMessageDTO.setParams(JSON.toJSONString(params));
            log.info("[{}]改价格发送app消息-开始", orderWork.getOrderId());
            Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
            log.info("[{}]改价格发送app消息结果：【{}】-结束", orderWork.getOrderId(), isSuccess);
        }

        /*Integer originalAmount = dbOrderWork.getOriginalAmount();
        Integer depositAmount = updatePriceDTO.getDepositAmount();

        WorkUpdateAmountDTO updateAmountDTO = new WorkUpdateAmountDTO();
        updateAmountDTO.setOrderId(updatePriceDTO.getOrderId());
        updateAmountDTO.setWorkId(updatePriceDTO.getWorkId());
        updateAmountDTO.setOriginalAmount(originalAmount);
        updateAmountDTO.setDepositAmount(depositAmount);
        updateAmountDTO.setEqutityId(updatePriceDTO.getEqutityId());
        updateAmountDTO.setOnlyVisit(updatePriceDTO.getOnlyVisit());*/
        // 只改定金
        /*if (updatePriceDTO.getDepositAmount() != null) {
            // 计算和更新工单金额
            ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(dbOrderWork);
            calcOrderAmountDIO.setNewDepositAmount(updatePriceDTO.getDepositAmount());
            OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.MODIFY_ORDER_DEPOSIT, calcOrderAmountDIO);
            orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO,dbOrderWork);
            //orderWorkAmountBService.updateDepositAmount(updateAmountDTO);
            OrderPay orderPay = new OrderPay();
            orderPay.setOrderId(updatePriceDTO.getOrderId());
            orderPay.setOrderPayId(updatePriceDTO.getDepositOrderPayId());
            orderPay.setAmount(updatePriceDTO.getDepositAmount());
            orderPay.setUpdater(updatePriceDTO.getOperator());
            orderPayService.updateByPrimaryKeySelective(orderPay);
        } else if (Objects.nonNull(updatePriceDTO.getProgressAmount())) {
            OrderPay orderPay = new OrderPay();
            orderPay.setOrderId(updatePriceDTO.getOrderId());
            orderPay.setOrderPayId(updatePriceDTO.getProgressOrderPayId());
            orderPay.setAmount(updatePriceDTO.getDepositAmount());
            orderPay.setUpdater(updatePriceDTO.getOperator());
            orderPayService.updateByPrimaryKeySelective(orderPay);
        }*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_PLAT_UPDATE_PRICE)
    public void saveUpdatePriceForEngineer(ZsUpdatePriceDTO updatePriceDTO) throws OmsBaseException {

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(updatePriceDTO.getOrderId(), updatePriceDTO.getWorkId());

        // 定金已支付不可操作
        Integer depositStatus = dbOrderWork.getDepositStatus();
        if (Objects.equals(PayConsts.PAY_STATUS_DONE, depositStatus)) {
            throw new OmsBaseException("定金已支付，不可改定金");
        }

        OperatePermissionVO operatePermission = orderWorkOperatePermissionBService.getOperatePermission(updatePriceDTO.getOrderId(), updatePriceDTO.getWorkId(), OrderConsts.ORDER_OP_TYPE_UPDATE_PRICE);
        if (!operatePermission.getCanOperate()) {
            throw new OmsBaseException(operatePermission.getMsg());
        }

        /*Integer originalAmount = dbOrderWork.getOriginalAmount();
        Integer depositAmount = updatePriceDTO.getDepositAmount();

        WorkUpdateAmountDTO updateAmountDTO = new WorkUpdateAmountDTO();
        updateAmountDTO.setOrderId(updatePriceDTO.getOrderId());
        updateAmountDTO.setWorkId(updatePriceDTO.getWorkId());
        updateAmountDTO.setOriginalAmount(originalAmount);
        updateAmountDTO.setDepositAmount(depositAmount);
        updateAmountDTO.setEqutityId(updatePriceDTO.getEqutityId());
        updateAmountDTO.setOnlyVisit(updatePriceDTO.getOnlyVisit());*/
        // 只改定金
        if (updatePriceDTO.getDepositAmount() != null) {
            // 计算和更新工单金额
            ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(dbOrderWork);
            calcOrderAmountDIO.setNewDepositAmount(updatePriceDTO.getDepositAmount());
            OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.MODIFY_ORDER_DEPOSIT, calcOrderAmountDIO, null);
            orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, dbOrderWork);
            //orderWorkAmountBService.updateDepositAmount(updateAmountDTO);
        }
    }

    @Override
    public ZsUpdatePriceVO findDiscountListUpdatePrice(ZsUpdatePriceDTO updatePriceDTO)
            throws OmsBaseException {
        WorkUpdateAmountDTO updateAmountDTO = BeanMapper
                .map(updatePriceDTO, WorkUpdateAmountDTO.class);
        OrderWork dbOrderWork = orderWorkService
                .findOrderWorkByKey(updatePriceDTO.getOrderId(), updatePriceDTO.getWorkId());

        // 原价变动获取最新的优惠
        ChangeOriginalAmountDiscountBO discountBO = orderWorkAmountBService
                .getDiscountAmountByOriginalAmountChange(updateAmountDTO, dbOrderWork);
        MemberDiscountDTO memberDiscountDTO = discountBO.getMemberDiscountDTO();

        // 当前优惠列表
        List<OrderDiscount> discountList = discountBO.getOrderDiscountList();
        List<ZsUpdatePriceDiscountVO> discountVOList = BeanMapper
                .mapList(discountList, ZsUpdatePriceDiscountVO.class);
        discountVOList.forEach(discount -> {
            discount.setCategName(FicoConsts.getDiscountCategName(discount.getCateg()));
            discount.setTypeName(OrderConsts.getDiscountTypeName(discount.getType()));
        });

        ZsUpdatePriceVO updatePriceVO = new ZsUpdatePriceVO();
        updatePriceVO.setOrderId(updatePriceDTO.getOrderId());
        updatePriceVO.setWorkId(updatePriceDTO.getWorkId());
        updatePriceVO.setEqutityId(memberDiscountDTO != null ? memberDiscountDTO.getEqutityId() : null);
        updatePriceVO.setDiscountAmount(discountBO.getDiscountAmount());
        updatePriceVO.setDiscountVOList(discountVOList);
        return updatePriceVO;
    }

    @Override
    public ZsUpdateChannelPrepayAmountVO findUpdateChannelPrepayAmountVO(Long orderId,
                                                                         Long workId) throws OmsBaseException {
        ZsUpdateChannelPrepayAmountVO channelPrepayAmountVO = new ZsUpdateChannelPrepayAmountVO();
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        channelPrepayAmountVO.setOrderId(dbOrderWork.getOrderId());
        channelPrepayAmountVO.setWorkId(dbOrderWork.getWorkId());
        channelPrepayAmountVO.setChannelPrepayAmount(dbOrderWork.getChannelPrepayAmount());

        if (dbOrderWork.getOriginalAmount() != null) {
            // 边界公式：订单金额-优惠-定金- 啄木鸟预收
            Integer originalAmount = Optional.ofNullable(dbOrderWork.getOriginalAmount()).orElse(0);
            Integer discountAmount = Optional.ofNullable(dbOrderWork.getDiscountAmount()).orElse(0);
            Integer depositAmount = Optional.ofNullable(dbOrderWork.getDepositAmount()).orElse(0);
            Integer prepayAmount = Optional.ofNullable(dbOrderWork.getPrepayAmount()).orElse(0);
            int maxPrepayAmount = originalAmount - discountAmount - depositAmount - prepayAmount;
            channelPrepayAmountVO.setMaxPrepayAmount(maxPrepayAmount);
        } else {
            channelPrepayAmountVO.setMaxPrepayAmount(10000000 * 100);
        }

        // 渠道预收凭证
        OrderExtend orderExtend = orderExtendService.findMiniOrderExtendByOrderId(orderId);
        if (orderExtend != null) {
            channelPrepayAmountVO.setChannelPrepayCertificateSrc(orderExtend.getChannelPrepayCertificateSrc());
        }

        ConfOrderChannelDRO confOrderChannelDRO = null;
        try {
            confOrderChannelDRO = confOrderChannelBService.getByChannelId(dbOrderWork.getChannelId());
        } catch (OmsBaseException e) {
            throw new OmsBaseException("查询渠道配置超时");
        }

        // 渠道配置不为空，并且预付款明细不为空
        if (Objects.nonNull(confOrderChannelDRO) && StringUtil.isNotBlank(confOrderChannelDRO.getPrepayAmountDetail())) {
            List<String> strList = StringUtil.splitStrs(confOrderChannelDRO.getPrepayAmountDetail());
            List<KVDict> result = Lists.newArrayListWithCapacity(strList.size());
            for (int i = 0; i < strList.size(); i++) {
                result.add(KVDict.builder().text(strList.get(i)).build());
            }
            channelPrepayAmountVO.setChannelPrepayAmountDetailList(result);
        }

        List<OrderChannelPrepay> channelPrepayList = orderChannelPrepayService.listOrderChannelPrepayByOrderIdAndWorkId(orderId, workId);
        // 如果订单保存的明细不为空
        if (CollectionUtil.isNotNullOrEmpty(channelPrepayList)) {
            int sum = channelPrepayList.stream().mapToInt(OrderChannelPrepay::getAmount).sum();
            channelPrepayAmountVO.setChannelPrepayAmount(channelPrepayAmountVO.getChannelPrepayAmount() - sum);
            // 如果渠道配置预付款明细为空，查询订单保存的明细
            if (CollectionUtil.isNullOrEmpty(channelPrepayAmountVO.getChannelPrepayAmountDetailList())) {
                List<KVDict> detalList = Lists.newArrayListWithCapacity(channelPrepayList.size());
                channelPrepayList.forEach(e -> {
                    detalList.add(KVDict.builder().text(e.getPrepayTypeName()).value(MoneyUtil.parseToYuan(e.getAmount())).build());
                });
                channelPrepayAmountVO.setChannelPrepayAmountDetailList(detalList);
            } else {
                // 如果配置和订单预付明细都不是空，开始合并结果
                List<KVDict> resultList = Lists.newArrayListWithCapacity(channelPrepayAmountVO.getChannelPrepayAmountDetailList().size());

                Map<String, KVDict> map = channelPrepayAmountVO.getChannelPrepayAmountDetailList().stream()
                        .collect(Collectors.toMap(KVDict::getText, e -> e, (entity1, entity2) -> entity1));

                channelPrepayList.forEach(e -> {
                    KVDict dict = map.get(e.getPrepayTypeName());
                    if (Objects.isNull(dict)) {
                        resultList.add(KVDict.builder().text(e.getPrepayTypeName()).value(MoneyUtil.parseToYuan(e.getAmount())).build());
                    } else {
                        dict.setValue(MoneyUtil.parseToYuan(e.getAmount()));
                        resultList.add(dict);
                        map.remove(e.getPrepayTypeName());
                    }
                });
                if (CollectionUtil.isNotNullOrEmpty(map)) {
                    List<KVDict> remainList = Lists.newArrayList(map.values());
                    resultList.addAll(remainList);
                }
                channelPrepayAmountVO.setChannelPrepayAmountDetailList(resultList);
            }
        }

        return channelPrepayAmountVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_PAY)
    public void saveChannelPrepayAmountPay(ZsUpdateChannelPrepayAmountDTO channelPrepayAmountDTO) throws Exception {
        channelPrepayAmountDTO.setIsJudgeOperateAuthority(true);
        this.saveChannelPrepayAmount(channelPrepayAmountDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OrderWorkCasOperate(type = OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT)
    public void saveChannelPrepayAmount(ZsUpdateChannelPrepayAmountDTO channelPrepayAmountDTO) throws OmsBaseException {

        Integer operatorType = null;
        if (Objects.equals(GlobalConsts.OPERATE_USER_TYPE_CHANNEL, channelPrepayAmountDTO.getOperatorType())) {
            operatorType = GlobalConsts.OPERATE_USER_TYPE_CHANNEL;
        }
        if (channelPrepayAmountDTO.getIsJudgeOperateAuthority()) {
            OperatePermissionVO operatePermission = orderWorkOperatePermissionBService.getOperatePermission(
                    channelPrepayAmountDTO.getOrderId(),
                    channelPrepayAmountDTO.getWorkId(),
                    OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT,
                    operatorType);
            if (!operatePermission.getCanOperate()) {
                throw new OmsBaseException(operatePermission.getMsg());
            }
        }

        Long orderId = channelPrepayAmountDTO.getOrderId();
        Long workId = channelPrepayAmountDTO.getWorkId();

        Integer channelPrepayAmount = Objects.equals(channelPrepayAmountDTO.getRemove(), GlobalConsts.YES) ? 0 : channelPrepayAmountDTO.getChannelPrepayAmount();
/*        // 1. 改金额
        WorkUpdateAmountDTO updateAmountDTO = new WorkUpdateAmountDTO();
        updateAmountDTO.setOrderId(orderId);
        updateAmountDTO.setWorkId(workId);
        Integer remove = channelPrepayAmountDTO.getRemove();
        if (Objects.equals(remove, GlobalConsts.YES)) {
            updateAmountDTO.setChannelPrepayAmount(0);
        } else {
            updateAmountDTO.setChannelPrepayAmount(channelPrepayAmountDTO.getChannelPrepayAmount());
        }
        orderWorkAmountBService.updateChannelPrepayAmount(updateAmountDTO);*/

        // 1，计算和更新工单金额
        OrderWork dbOrderWork = Optional.ofNullable(channelPrepayAmountDTO.getOrderWork()).orElse(orderWorkService.findOrderWorkByKey(orderId, workId));
        ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(dbOrderWork);
        calcOrderAmountDIO.setNewChannelPrepayAmount(channelPrepayAmount);
        OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.MODIFY_ORDER_CHANNEL_PREPAYAMOUNT, calcOrderAmountDIO, null);
        orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, dbOrderWork);

        // 2. 改支付状态
        OrderWork updateAmount = new OrderWork();
        updateAmount.setOrderId(orderId);
        updateAmount.setWorkId(workId);

        // 已删除渠道预付 渠道预付状态设置未付款
        boolean remove = Objects.equals(channelPrepayAmountDTO.getRemove(), GlobalConsts.YES);
        if (remove) {
            updateAmount.setChannelPrepayStatus(PayConsts.PAY_STATUS_NONE);
        } else {
            updateAmount.setChannelPrepayStatus(PayConsts.PAY_STATUS_DONE);
            updateAmount.setDisableDiscard(GlobalConsts.NO);
        }
        orderWorkAmountService.updatePayStatusChannelPrepay(updateAmount);

        // 删除预付凭证
        if (remove) {
            orderExtendService.clearChannelPrepayCertificateSrcByKey(orderId);
        } else {
            // 更新凭证
            if (StringUtils.isNotBlank(channelPrepayAmountDTO.getChannelPrepayCertificateSrc())) {
                OrderExtend orderExtend = new OrderExtend();
                orderExtend.setExtId(orderId);
                orderExtend.setChannelPrepayCertificateSrc(channelPrepayAmountDTO.getChannelPrepayCertificateSrc());
                // 更新渠道预收凭证
                orderExtendService.updateOrderExtend(orderExtend);
            }
        }

        // 改价格删除尾款验收，需要工程师重新发起尾款验收
        OrderWorkAcceptanceDTO dto = new OrderWorkAcceptanceDTO();
        dto.setOrderId(channelPrepayAmountDTO.getOrderId());
        dto.setWorkId(channelPrepayAmountDTO.getWorkId());
        dto.setOperator(channelPrepayAmountDTO.getOperator());
        dto.setOperatorId(channelPrepayAmountDTO.getOperatorId());
        dto.setOperatorType(channelPrepayAmountDTO.getOperatorType());
        orderWorkAcceptanceBService.clearPaymentAcceptance(dto, dbOrderWork);

        // 先删除再插入预付款明细
        orderChannelPrepayService.deleteByOrderId(channelPrepayAmountDTO.getOrderId());
        if (CollectionUtil.isNotNullOrEmpty(channelPrepayAmountDTO.getChannelPrepayAmountDetailList())) {
            List<OrderChannelPrepay> channelPrepayList = Lists.newArrayListWithCapacity(channelPrepayAmountDTO.getChannelPrepayAmountDetailList().size());
            channelPrepayAmountDTO.getChannelPrepayAmountDetailList().forEach(e -> {
                OrderChannelPrepay prepay = new OrderChannelPrepay();
                prepay.setOrderId(channelPrepayAmountDTO.getOrderId());
                prepay.setWorkId(channelPrepayAmountDTO.getWorkId());
                prepay.setPrepayTypeName(e.getText());
                prepay.setAmount(Integer.parseInt(e.getValue().toString()));
                prepay.setCreater(channelPrepayAmountDTO.getOperator());
                prepay.setUpdater(channelPrepayAmountDTO.getOperator());
                channelPrepayList.add(prepay);
            });
            orderChannelPrepayService.insertAll(channelPrepayList);
        }
    }

    /**
     * 工单完成
     *
     * @param completeDTO
     */
    @Override
    public void completeOrder(CompleteDTO completeDTO) throws OmsBaseException {
        String lockKey = String.format("%s_%s", completeDTO.getOrderId(), completeDTO.getWorkId());
        DistributedLock lock = DistributedLockUtils.build(LockConsts.LOCK_ORDER_COMPLETE_PAY + lockKey, 10);
        try {
            if (lock.tryLock()) {
                zsMasterWorkBService.completeOrder(completeDTO);
            }
        } catch (OmsBaseException e) {
            throw e;
        } catch (Exception e) {
            log.error("完成异常:" + e.getMessage(), e);
            throw e;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 工单完成检查
     *
     * @param completeDTO
     */
    @Override
    public void checkComplete(CompleteDTO completeDTO) throws OmsBaseException {

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(completeDTO.getOrderId(), completeDTO.getWorkId());
        if (orderWork == null) {
            throw new OmsBaseException("工单不存在");
        }
        completeDTO.setChannelId(orderWork.getChannelId());

        if (Objects.equals(orderWork.getRefundReviewStatus(), OrderConsts.REVIEW_STATUS_DOING)) {
            throw new OmsBaseException("申请退款中，不能操作完成");
        }
        if (completeDTO.getMasterId() != null) {
            if (!Objects.equals(completeDTO.getMasterId(), orderWork.getMasterId())) {
                throw new OmsBaseException("无效工单");
            }
        }

        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            throw new OmsBaseException("工单不在进行中");
        }

        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_DISTRIBUTE
                || orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {
            throw new OmsBaseException("工单状态不能完成");
        }

        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK) && NumberUtil
                .isNullOrZero(orderWork.getOriginalAmount())) {
            throw new OmsBaseException("工单原价不能为空，请检查勾选服务项目");
        }

        if (ChannelConsts.CHANNEL_ID_NOSUPPORT_ACCOUNT_PAY.contains(orderWork.getChannelId())
                && NumberUtil.isNotNullOrZero(orderWork.getMasterAmount())) {
            throw new OmsBaseException("天猫订单，不能存在工程师收款");
        }

        if (Objects.nonNull(completeDTO.getMasterId())) {
            this.completeNonPayAmount(orderWork);
        }

        // 京东到家校验完成码
        if ((Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_JD_DAOJIA) ||
                Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_JD_QTDJ)) &&
                !Objects.equals(completeDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_SYSTEM) &&
                !Objects.equals(completeDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_STAFF)) {
            boolean verifyComplete = jddjService.verifyComplete(orderWork.getOrderId(), orderWork.getWorkId());
            if (!verifyComplete) {
                throw new OmsBaseException("操作失败，请前往工程师端核销码页填写核销码");
            }
        }

        // 渠道核销码校验
        if (ChannelConsts.CHANNEL_ID_NEED_INPUT_COMPLETE_CODE.contains(orderWork.getChannelId())) {
            completeCodeBService.verifyCompleteCodeExists(orderWork.getOrderId(), orderWork.getWorkId());
        }

        // 天猫勤鸽保外校验完成码，2021/07/15 xwb
        if (Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_QINGE_BW)) {
            boolean verifyComplete = tmallService.verifyComplete(orderWork.getOrderId(), orderWork.getWorkId());
            if (!verifyComplete) {
                throw new OmsBaseException("操作失败，请前往工程师端核销码页填写核销码");
            }
        }

        /**
         * 啄木鸟和言而有信，先判断统一条件，然后再分开判断
         */

        /**
         * 1.统一条件
         */

        // 标准收费单检测服务项是否填写
        if (Objects.equals(orderWork.getStandardPrice(), GlobalConsts.YES)) {
            int serviceItemCount = orderServiceItemService.countProExtIdByOrderId(completeDTO.getOrderId());
            if (serviceItemCount == 0) {
                throw new OmsBaseException("请勾选选服务项目");
            }

            // 判断服务项的扩展产品数量是否相等
            int proExtCount = orderProductExtendService.countByOrderId(completeDTO.getOrderId());
            if (proExtCount != serviceItemCount) {
                throw new OmsBaseException("服务项目未填写完成，请完善");
            }
        }

        /* 校验是否需要补全增值资料 */
        /* 啄安保已经停掉，验证去掉   谢文兵 2022.06.30
        ResponseDTO<Long> isDoing = vasOrderListRemoteService.isDoing(orderWork.getWorkId());
        if (isDoing.isSuccess()) {
            throw new OmsBaseException("请先点击“啄安保”，完善保单资料或支付");
        }
         */


        // 新单，配件金额之和不得大于订单收入
        // 要客不做金额限制 modify by liuying 2021-10-11
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
        // 新单，配件金额之和不得大于订单收入
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                && !Objects.equals(orderDetail.getVvip(), GlobalConsts.YES)) {
            List<OrderPart> parts = orderPartService.listByOrderId(orderWork.getOrderId());
            if (CollectionUtil.isNotNullOrEmpty(parts)) {
                Integer partTotalAmount = parts.stream().mapToInt(item -> {
                    return MathUtil.amountMultiplyNumber(item.getPrice(), item.getNumber());
                }).sum();
                if (partTotalAmount > orderWork.getTotalAmount()) {
                    throw new OmsBaseException("配件金额大于订单收入，不可完成");
                }
            }
        }

        /**
         * 2.分条件处理，目前是(厂商工单&保内)和其他两个条件
         */

        // 保内&厂商单
        if (Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY)
                && Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)) {

            // 检查照片
            OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
            if (orderExtend == null || StringUtil.isBlank(orderExtend.getImageSrc())) {
                throw new OmsBaseException("请上传照片");
            }

            // 厂商配件检查
            FcOrderPartCheckDTO fcPartCheck = orderFactoryPartService.doFactoryPartCheck(orderWork.getOrderId());
            if (fcPartCheck.isContainsFcPart()) {
                // 配件审核中或厂商配件快递状态：未发货，不可操作完成，不可操作提示语：言而有信：配件审核中或厂商配件快递状态：未发货，不可操作完成
                if (fcPartCheck.isContainsWaiting4FcReview() || fcPartCheck.isContainsFcPartWaiting4Post()) {
                    throw new OmsBaseException("配件审核中或厂商配件快递状态：未发货，不可操作完成");
                }
                // 厂商配件需：旧件返厂，工程师未填写快递信息，不可操作完成，弹框提示：您有旧件需要返厂，请处理
                if (fcPartCheck.isNeedReturnFcPart() && fcPartCheck.isContainsReturnFcPartWaiting4Post()) {
                    throw new OmsBaseException("您有旧件需要返厂，请处理");
                }
            }
        } // 厂商工单&保内
        else { // 其他（非 厂商工单&保内）

            // 啄木鸟平台
            boolean isZmnPlat = Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN);
            // 川南环保平台
            boolean isCnhbPlat = Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_CNHB);

            // 检查定金支付状态，填了定金且未支付，提示支付定金后再完成
            if (orderWork.getDepositAmount() != null && orderWork.getDepositAmount() > 0 && Objects
                    .equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_NONE)) {
                throw new OmsBaseException("请支付定金后再完成");
            }

            // 工单没有支付，检测工程师收款是否为空
            if ((orderWork.getTotalAmount() == null || orderWork.getMasterAmount() == null) && !Objects
                    .equals(orderWork.getPayStatus(), PayConsts.PAY_STATUS_DONE)) {
                if (Objects.equals(orderWork.getStandardPrice(), GlobalConsts.YES)) {
                    throw new OmsBaseException("请勾选选服务项目");
                } else {
                    throw new OmsBaseException("请输入实收价格");
                }
            }

            // 会员单，检测审核
            if (Objects.equals(orderWork.getMember(), GlobalConsts.YES)) {
                OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
                if (orderMember == null) {
                    throw new OmsBaseException("会员订单不存在");
                }

                if (Objects.equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_FAIL)) {
                    throw new OmsBaseException("会员订单审核失败");
                }

                if (Objects.equals(orderMember.getVerify(), GlobalConsts.YES) && Objects
                        .equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_MASTER)) {
                    throw new OmsBaseException("会员订单需要审核后才能操作");
                }
            }

            // 工程师代理商标志
            Integer masterAgent = null;
            if (completeDTO.getAgent() != null) {
                masterAgent = completeDTO.getAgent();
            } else {
                // todo fubiao
                log.info("checkComplete#getEngineerDetailById 入参 [{}]", orderWork.getMasterId());
                ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(orderWork.getMasterId());
                log.info("checkComplete#getEngineerDetailById 出参 [{}]", JSON.toJSONString(cacheEngineerByEngineerId));
                ForeignEngineerDetailInfoDRO mastMasterDRO = cacheEngineerByEngineerId.getData();
                if (cacheEngineerByEngineerId.isSuccess() && mastMasterDRO != null) {
                    masterAgent = mastMasterDRO.getCooperationType();
                }
            }

            // 啄木鸟平台，校验贴花和配件
            if (isZmnPlat) {
                // 校验贴花照片
//                boolean needApplique = false;
//                ConfOrderChannelDRO confOrderChannelDRO = confOrderChannelBService.getByChannelId(orderWork.getChannelId());
//                if (Objects.nonNull(confOrderChannelDRO)) {
//                    // 渠道是否需要贴花标志，1：否，2：是
//                    if (Objects.equals(confOrderChannelDRO.getApplique(), GlobalConsts.YES)) {
//                        needApplique = true;
//                    }
//                }
//                OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
//                if (needApplique) {
//                    if (orderExtend == null || StringUtil.isBlank(orderExtend.getAppliqueSrc())) {
//                        throw new OmsBaseException("请将贴花贴于用户家中，并现场拍照");
//                    }
//                }
                /*if (orderExtend == null || StringUtils.isBlank(orderExtend.getMasterSrc()) && Objects
                        .equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
                    throw new OmsBaseException("请上传个人形象照片");
                }*/
                // 校验配件
                if (orderWork.getPartUse() == 0 && !Objects.equals(orderWork.getPartRetain(), GlobalConsts.YES)) {
                    throw new OmsBaseException("配件未选择");
                }
            } // 啄木鸟平台，校验贴花和配件

            //            if (isCnhbPlat) {
            // 川南环保校验配件 2019-9-17 02:25:55 高阳确认川南环保不需要校验配件
/*                if (orderWork.getPartUse() == 0) {
                    throw new OmsBaseException("配件未选择");
                }*/
            //            }

            if (!Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
                // 是否有保修信息
                Map<Long, Integer> warrantyMap = orderWarrantyBService.isExistWarrantyInfoMap(orderWork.getOrderId(), orderWork.getWorkId());
                boolean existWarrantyInfo = warrantyMap.containsValue(GlobalConsts.YES);

                // 是否啄木鸟自营
                boolean zmnDirectly = isZmnPlat && Objects.equals(masterAgent, 1);

                if (completeDTO.getVersion() != null && completeDTO.getVersion() < 46 && (isZmnPlat || isCnhbPlat)) { //
                    // 版本号小于46 此处校验临时处理
                    // 等app 发版后可以删除
                    // 啄木鸟直营工程师
                    if (zmnDirectly) {
                        if (PremissUtil.needSelectWarrantyFault(orderWork.getServCategId())) {
                            int count = orderWarrantyProductService.countProExtIdByOrderId(orderWork.getOrderId());
                            if (count == 0) {
                                throw new OmsBaseException("请填写保修范围");
                            }
                            // 判断保修的扩展产品存在保修的数量是否相等
                            int proExtCount = orderProductExtendService.countByOrderId(completeDTO.getOrderId());
                            if (proExtCount != count) {
                                throw new OmsBaseException("请填写保修范围，输入不完整");
                            }
                        }
                    } // 啄木鸟直营工程师
                } else {
                    // 啄木鸟直营工程师
                    if (existWarrantyInfo && (isZmnPlat || isCnhbPlat)) {
                        // if (PremissUtil.needSelectWarrantyFault(orderWork.getServCategId())) {
                        int count = orderWarrantyProductService.countProExtIdByOrderId(orderWork.getOrderId());
                        if (count == 0) {
                            throw new OmsBaseException("请完善保修信息");
                        }

                        int proExtCount = 0;
                        for (Map.Entry<Long, Integer> entry : warrantyMap.entrySet()) {
                            if (Objects.equals(GlobalConsts.YES, entry.getValue())) {
                                proExtCount++;
                            }
                        }

                        // 判断保修的扩展产品存在保修的数量是否相等
                        //int proExtCount = orderProductExtendService.countByOrderId(completeDTO.getOrderId());
                        if (proExtCount != count) {
                            throw new OmsBaseException("请完善保修信息，输入不完整");
                        }
                        //  }
                    } // 啄木鸟直营工程师
                }
            }

            this.completeCheckPartInfo(orderWork);
        } // 其他（非 厂商工单&保内）

        // 校验多次收款
        List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterIdSrcMaster(orderWork.getOrderId(), orderWork.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(orderVisitList)) {
            boolean noVisit = orderVisitList.stream()
                    .anyMatch(e -> Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY)
                            || Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT));
            if (noVisit) {
                throw new OmsBaseException("工单需再次上门，不可操作");
            }

            boolean noPay = orderVisitList.stream()
                    .filter(e -> NumberUtil.isNotNullOrZero(e.getAcceptanceId())
                            || NumberUtil.isNotNullOrZero(e.getOrderPayId()))
                    .filter(e -> !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL))
                    .anyMatch(e -> Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_NONE));
            if (noPay) {
                throw new OmsBaseException("工单未支付，不可操作");
            }
        }

        // 返修单申请的退款单，如果退款单未完成，则该返修单不能完成
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            OrderWork original = orderWorkService.findOrderWorkByKey(orderWork.getOriginalId(), orderWork.getOriginalId());
            if (NumberUtil.isNotNullOrZero(original.getRefundTargetWorkId())) {
                OrderWork reworkRefund = orderWorkService.findOrderWorkByKey(original.getOrderId(), original.getRefundTargetWorkId());
                if (reworkRefund.getStatus() < OrderStatusConsts.ORDER_STATUS_COMPLETE
                        && Objects.equals(reworkRefund.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)
                        && Objects.equals(orderWork.getOrderId(), reworkRefund.getRefundWorkId())) {
                    throw new OmsBaseException("存在未完结的退款申请，无法完成服务");
                }
            }
        }
    }


    /**
     * 工单服务完成检查
     *
     * @param serviceCompleteDIO
     */
    @Override
    public OrderWork checkServiceComplete(ServiceCompleteDIO serviceCompleteDIO) throws OmsBaseException {

        // 智米订单在完成前，需先同步给对方完成状态
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(serviceCompleteDIO.getOrderId(), serviceCompleteDIO.getWorkId());

        if (Objects.isNull(orderWork.getOriginalAmount())) {
            throw new OmsBaseException("收款金额不能为空");
        }

        // 检查照片
      /*  OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
        if (orderExtend == null || StringUtil.isBlank(orderExtend.getImageSrc())) {
            throw new OmsBaseException("请上传照片");
        }*/

        // 检查服务项
        int serviceItemCount = orderServiceItemService.countProExtIdByOrderId(orderWork.getOrderId());
        if (serviceItemCount == 0) {
            throw new OmsBaseException("请勾选选服务项目");
        }

        // 计价器3.0完成校验 配件是否使用
        this.completeCheckPartInfo(orderWork);

        if (ChannelConsts.CHANNEL_ID_NOSUPPORT_ACCOUNT_PAY.contains(orderWork.getChannelId())
                && NumberUtil.isNotNullOrZero(orderWork.getMasterAmount())) {
            throw new OmsBaseException("天猫订单，不能存在工程师收款");
        }

        // 厂商单
        if (Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY)) {
            // 厂商配件检查
            FcOrderPartCheckDTO fcPartCheck = orderFactoryPartService.doFactoryPartCheck(orderWork.getOrderId());
            if (fcPartCheck.isContainsFcPart()) {
                // 配件审核中或厂商配件快递状态：未发货，不可操作完成，不可操作提示语：言而有信：配件审核中或厂商配件快递状态：未发货，不可操作完成
                if (fcPartCheck.isContainsWaiting4FcReview() || fcPartCheck.isContainsFcPartWaiting4Post()) {
                    throw new OmsBaseException("配件审核中或厂商配件快递状态：未发货，不可操作完成");
                }
                // 厂商配件需：旧件返厂，工程师未填写快递信息，不可操作完成，弹框提示：您有旧件需要返厂，请处理
                if (fcPartCheck.isNeedReturnFcPart() && fcPartCheck.isContainsReturnFcPartWaiting4Post()) {
                    throw new OmsBaseException("您有旧件需要返厂，请处理");
                }
            }
        }

        // 检查渠道必传照片和视频是否上传
//        OrderAttachmentQuery orderAttachmentQuery = new OrderAttachmentQuery();
//        orderAttachmentQuery.setOrderId(orderWork.getOrderId());
//        orderAttachmentQuery.setWorkId(orderWork.getWorkId());
//        orderAttachmentQuery.setBizType(orderWork.getBizType());
//        orderAttachmentQuery.setChannelId(orderWork.getChannelId());
//        orderAttachmentQuery.setServCategId(orderWork.getServCategId());
//        OperatePermissionVO operatePermissionVO = zsOrderWorkOperatePermissionBService.requireOrderChannelAttachment(orderAttachmentQuery);
//        if (!operatePermissionVO.getCanOperate()) {
//            throw new OmsBaseException(operatePermissionVO.getMsg());
//        }

        return orderWork;
    }


    /**
     * 记录工程师联系用户
     *
     * @param contactUserDTO
     */
    @Override
    public void saveContactUser(ContactUserDTO contactUserDTO) throws Exception {
        zsMasterWorkBService.saveContactUser(contactUserDTO);
    }

    private void completeCheckPartInfo(OrderWork orderWork) throws OmsBaseException {
        if (!Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
            return;
        }
        if (Objects.equals(orderWork.getPartRetain(), GlobalConsts.YES)) {
            return;
        }
        List<OrderServiceItem> orderServiceItems = orderServiceItemService.listByOrderId(orderWork.getOrderId());
        if (CollectionUtil.isNullOrEmpty(orderServiceItems)) {
            throw new OmsBaseException("请勾选选服务项目");
        }
        List<Integer> serviceItemIdList = orderServiceItems
                .stream()
                .map(OrderServiceItem::getServItemId)
                .collect(Collectors.toList());
        log.info("serviceItemListRemoteService.getItemPartByItemId serviceItemIdList={}", serviceItemIdList);
        ResponseDTO<List<ItemPartsDRO>> responseDTO = itemPartsRemoteService.listItemPartByItemIds(serviceItemIdList);
        log.info("serviceItemListRemoteService.getItemPartByItemId responseDTO={}", JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getMessage());
        }
        // 如果服务项关联配件，则需要使用内采配件或者外报配件
        if (CollectionUtil.isNotNullOrEmpty(responseDTO.getData())) {
            // 内采
            boolean notInPart = false;
            SingleMasterOrderPartDTO singleMasterOrderPartDTO = orderPartBService.listByOrderIdAndMaster(orderWork.getOrderId(), orderWork.getMasterId());
            if (CollectionUtil.isNullOrEmpty(singleMasterOrderPartDTO.getInParts())) {
                notInPart = true;
            }

            // 外报
            boolean notOutPart = false;
            ScmPurchaseApplyQuery scmPurchaseFreightQuery = new ScmPurchaseApplyQuery();
            scmPurchaseFreightQuery.setSourceId(String.valueOf(orderWork.getWorkId()));
            ResponseDTO<List<ScmPurchaseApplyDRO>> listResponseDTO = engineerPurchaseListRemoteService.listByQueryV2(scmPurchaseFreightQuery);
            if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
                notOutPart = true;
            }

            if (notInPart && notOutPart) {
                throw new OmsBaseException("服务含配件，请先选择配件");
            }
        }

        // 一口价校验配件对比照
        if (Objects.equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
            Integer partUseType = zsNormalOrderPartBService.getPartUseType(orderWork);
            if (Objects.equals(partUseType, WorkPartUseTypeEnum.COMPARISON_IMG_NOT_UPLOADED.getType())) {
                throw new OmsBaseException("配件需核销，请上传对比照！");
            }
        }
    }

    /**
     * 完成收款未支付校验
     *
     * @param orderWork
     */
    private void completeNonPayAmount(OrderWork orderWork) throws OmsBaseException {
        TrackWorkQueryDIO trackWorkQueryDIO = new TrackWorkQueryDIO();
        trackWorkQueryDIO.setOrderId(orderWork.getOrderId());
        trackWorkQueryDIO.setWorkId(orderWork.getWorkId());
        trackWorkQueryDIO.setTrackContentIdList(Lists.newArrayList(TrackConfigConsts.TRACK_CONTENT_ID_COMPANY_MONEY,
                TrackConfigConsts.TRACK_CONTENT_ID_ENGINEER_MONEY_NO_PAY));
        trackWorkQueryDIO.setTrackStatusList(Lists.newArrayList(TrackConsts.TRACK_STATUS_PENDING, TrackConsts.TRACK_STATUS_PROCESSING));
        ResponseDTO<List<TrackWorkDRO>> responseDTO = trackWorkListRemoteService.listTrackWorkByQuery(trackWorkQueryDIO);
        if (responseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(responseDTO.getData())) {
            Integer noPayAmount = responseDTO.getData().stream().filter(e -> Objects.nonNull(e.getAmount())).mapToInt(TrackWorkDRO::getAmount).sum();
            if (orderWork.getTotalAmount() != null && noPayAmount > orderWork.getTotalAmount()) {
                throw new OmsBaseException(String.format("订单收入不能小于%s元，如有疑问请咨询内勤专员！", MoneyUtil.parseToYuanStr(noPayAmount)));
            }
        }
    }
}